#include "api_map.h"
#if API_ENABLE_CONFIG_UART
#include "esp_tls_crypto.h"
#include "http_server.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "mbedtls/base64.h"
#include "esp_log.h"
#include "io_config.h"

#define TAG "api.uart"
#define log_e(...) ESP_LOGE(TAG, __VA_ARGS__)
#define log_i(...) ESP_LOGI(TAG, __VA_ARGS__)
#define log_w(...) ESP_LOGW(TAG, __VA_ARGS__)

// UART_NUM_MAX
#include "config.h"
#define CONFIG_ITEM_NAME "UartConfig"
#define UART_HW_RX_BUFFER_SIZE 512                                                                            /* 可修改(建议为你需要的最大一帧大小) */
#define UART_HW_TX_BUFFER_SIZE 512                                                                            /* 可修改(建议为0) */
#define UART_ENCODED_DATA_MAX 512                                                                             /* 可修改 */
#define UART_ENCODED_BUFFER_SIZE (((UART_ENCODED_DATA_MAX / 3) + ((UART_ENCODED_DATA_MAX % 3) != 0)) * 4 + 1) /* 不可修改 */
#define UART_BUFFER_SIZE (128 + UART_ENCODED_BUFFER_SIZE)                                                     /* 128 可修改 */
#define GET_CONFIG_GPIO(num) ((num) == 255 ? -1 : (num))
#pragma pack(1)
typedef struct uart_storage
{
    uint32_t buffer;    // 缓冲区大小
    uint32_t baud_rate; /*!< UART baud rate*/
    struct
    {
        uint8_t tx;
        uint8_t rx;
        uint8_t rts;
        uint8_t cts;
    } io_map;
    uint8_t data_bits : 2; /*!< UART byte size (uart_word_length_t)*/
    uint8_t parity : 2;    /*!< UART parity mode (uart_parity_t) */
    uint8_t stop_bits : 2; /*!< UART stop bits (uart_stop_bits_t) */
    uint8_t enable : 1;
    struct uart_frame
    {
        uint8_t enable : 1; /* 断帧使能 */
        uint16_t break_ms;  /* 断帧时间 */
        uint8_t break_byte; /* 断帧字节 */
    } frame;
} uart_storage_s, *uart_storage_t;

typedef struct uart_configs
{
    uart_storage_s uart[UART_NUM_MAX];
} uart_configs_s, *uart_configs_t;

typedef struct uart_data
{
    uart_configs_s config;                                      // 配置
    TaskHandle_t task_handle[UART_NUM_MAX * 2];                 /* 任务句柄 */
    ring_buffer_t rb[UART_NUM_MAX];                             /* 用户配置的缓冲区大小 */
    uint8_t listen_rx;                                          /* 是否转发RX */
    uint8_t buffer[UART_NUM_MAX][UART_BUFFER_SIZE];             /* 缓冲区 */
    uint8_t readBuffer[UART_NUM_MAX][UART_ENCODED_BUFFER_SIZE]; /* 线程读取缓冲区 */
    uint8_t writeBuffer[UART_NUM_MAX][UART_ENCODED_DATA_MAX];   /* 线程写缓冲区 */
} uart_data_s, *uart_data_t;
#pragma pack()
uart_data_t uart_datas = NULL;

static bool uart_config_check(uint32_t baudrate, uint8_t data_bits, uint8_t parrity, uint8_t stop_bits)
{
    if (baudrate > 3686400 || data_bits >= UART_DATA_BITS_MAX || parrity > UART_PARITY_ODD || stop_bits >= UART_STOP_BITS_MAX)
        return false;
    return true;
}

static bool uart_config_check_io(uint8_t tx, uint8_t rx, uint8_t rst, uint8_t cts)
{
    if (tx >= CONFIG_SOC_GPIO_PIN_COUNT && tx != 255)
        return false;
    if (rx >= CONFIG_SOC_GPIO_PIN_COUNT && rx != 255)
        return false;
    if (rx == tx)
        return false;
    if (rst >= CONFIG_SOC_GPIO_PIN_COUNT && rst != 255)
        return false;
    if (cts >= CONFIG_SOC_GPIO_PIN_COUNT && cts != 255)
        return false;
    return true;
}

bool uart_init_pro(uint8_t port, uint32_t baudrate, uint8_t data_bits, uint8_t parrity, uint8_t stop_bits, uint16_t tx_bs, uint16_t rx_bs, int tx, int rx, int rst, int cts)
{
    if (!uart_config_check_io(tx, rx, rst, cts) || !uart_config_check(baudrate, data_bits, parrity, stop_bits) || port >= UART_NUM_MAX)
    {
        return false; // 非法引脚
    }
#if SOC_UART_SUPPORT_REF_TICK
    uart_sclk_t clk_source = UART_SCLK_REF_TICK;
    if (baudrate > 1 * 1000 * 1000)
    {
        clk_source = UART_SCLK_DEFAULT;
        log_e("uart%d light sleep UART wakeup might not work at the configured baud rate", port);
    }
#elif SOC_UART_SUPPORT_XTAL_CLK
    uart_sclk_t clk_source = UART_SCLK_XTAL;
#else
#error "No UART clock source is aware of DFS"
#endif // SOC_UART_SUPPORT_xxx
    uart_config_t cfg = {
        .baud_rate = baudrate,
        .data_bits = data_bits,
        .parity = parrity,
        .stop_bits = stop_bits,
        .source_clk = clk_source,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .rx_flow_ctrl_thresh = 0,
    };
    bool set_pin = tx != -1 || rx != -1 || rst != -1 || cts != -1;
    if (uart_is_driver_installed(port))
        uart_driver_delete(port);
    uart_driver_install(port, rx_bs, tx_bs, 0, NULL, 0);
    // Configure UART parameters
    esp_err_t err = uart_param_config(port, &cfg);
    if (err != ESP_OK)
    {
        log_e("uart%d param config failed: %s", port, esp_err_to_name(err));
        return false;
    }
    if (set_pin)
    {
        err = uart_set_pin(port, tx, rx, rst, cts);
        if (err != ESP_OK)
        {
            log_e("uart%d set pin failed: %s", port, esp_err_to_name(err));
            return false;
        }
    }
    if (port == 0)
        fflush(stdout);
    uart_flush_input(port);
    static const char parrity_str[] = {'N', 'N', 'E', 'O'};
    static const char stop_str[] = {'N', '1', '5', '2', 'M'};
    printf("[uart%d] baud rate : %8ld, data bits : %d, parity : %c, stop bits: %c, TX Buffer : %4d, RX Buffer : %4d", port, baudrate, data_bits + 5, parrity_str[parrity], stop_str[stop_bits], tx_bs, rx_bs);
    if (set_pin)
        printf(", TX : %2d, RX : %2d, RTS : %2d, CTS : %2d", tx, rx, rst, cts);
    printf("\r\n");
    if (port == 0)
        fflush(stdout);
    return true;
}

static bool uart_reconfig(uint8_t uart_num)
{
    return uart_init_pro(
        uart_num,
        uart_datas->config.uart[uart_num].baud_rate,
        uart_datas->config.uart[uart_num].data_bits,
        uart_datas->config.uart[uart_num].parity,
        uart_datas->config.uart[uart_num].stop_bits,
        UART_HW_TX_BUFFER_SIZE, UART_HW_RX_BUFFER_SIZE,
        GET_CONFIG_GPIO(uart_datas->config.uart[uart_num].io_map.tx),
        GET_CONFIG_GPIO(uart_datas->config.uart[uart_num].io_map.rx),
        GET_CONFIG_GPIO(uart_datas->config.uart[uart_num].io_map.rts),
        GET_CONFIG_GPIO(uart_datas->config.uart[uart_num].io_map.cts));
}

static void uart_task_stop(uint8_t uart_num)
{
    if (uart_datas->task_handle[uart_num])
    {
        vTaskDelete(uart_datas->task_handle[uart_num]);
        uart_datas->task_handle[uart_num] = NULL;
    }
}

static void uart_free_rb(uint8_t uart_num)
{
    uart_task_stop(uart_num);
    if (uart_datas->rb[uart_num])
    {
        ringbuffer_destroy(uart_datas->rb[uart_num]);
        uart_datas->rb[uart_num] = NULL;
    }
}

static void uart_rx_thread(void *p)
{
    uint8_t uart_num = (uint8_t)p;
    ring_buffer_t rb = uart_datas->rb[uart_num];
    uart_storage_t config = &uart_datas->config.uart[uart_num];
    uint8_t *cache = uart_datas->readBuffer[uart_num];
    uint8_t *buffer = uart_datas->buffer[uart_num];
    uint8_t rxBytes = 0, data = 0, recv = 0, send_msg = 0;
    log_i("uart %d rx thread start", uart_num);
    while (1)
    {
        uint16_t wait_ms = 10;
        if (config->frame.enable)
            wait_ms = config->frame.break_ms;
        rxBytes = uart_read_bytes(uart_num, &data, 1, pdMS_TO_TICKS(wait_ms));
        if (rxBytes > 0)
        {
            // gpio_set_level(GPIO_NUM_46, 0);
            if (!recv)
                recv = 1;
            ringbuffer_put(rb, &data, 1, pdMS_TO_TICKS(wait_ms));
            if (config->frame.enable && config->frame.break_byte && rb->size >= config->frame.break_byte)
                send_msg = 1;
            if (!send_msg && rb->size >= UART_ENCODED_DATA_MAX)
                send_msg = 1;
        }
        else if (recv)
        {
            recv = 0;
            // gpio_set_level(GPIO_NUM_46, 1);
            send_msg = 1;
        }
        if (send_msg)
        {
            send_msg = 0;
            recv = 0;
            if (uart_datas->listen_rx & (1 << uart_num))
            {
                while (rb->size)
                {
                    size_t base64Size = 0, msg_len = 0;
                    uint16_t size = rb->size;
                    if (size > UART_ENCODED_DATA_MAX)
                        size = UART_ENCODED_DATA_MAX;
                    if (config->frame.enable && config->frame.break_byte && size >= config->frame.break_byte)
                        size = config->frame.break_byte;
                    ringbuffer_get(rb, cache, size, pdMS_TO_TICKS(10));
                    msg_len += snprintf((char *)&buffer[msg_len], UART_BUFFER_SIZE - msg_len, "{\"uart\": {\"id\":%d, \"data\": \"", uart_num);
                    mbedtls_base64_encode((unsigned char *)&buffer[msg_len], UART_BUFFER_SIZE - msg_len, &base64Size, cache, size);
                    // log_i("buffer(%p) size %d, base64 size %d", cache, size, base64Size);
                    msg_len += base64Size;
                    msg_len += snprintf((char *)&buffer[msg_len], UART_BUFFER_SIZE - msg_len, "\"}}");
                    ws_send_msg(buffer, msg_len);
                }
            }
        }
    }
    log_w("uart %d rx thread stop", uart_num);
    vTaskDelete(NULL);
}

static bool uart_start(uint8_t uart_num, bool enable)
{
    uart_task_stop(uart_num);
    uart_free_rb(uart_num);
    if (uart_is_driver_installed(uart_num))
        uart_driver_delete(uart_num);

    if (enable)
    {
        if (!uart_reconfig(uart_num))
            return true; /* 仅保存 */

        if (uart_datas->config.uart[uart_num].buffer)
        {
            uart_datas->rb[uart_num] = ringbuffer_create(uart_datas->config.uart[uart_num].buffer);
            if (!uart_datas->rb[uart_num])
            {
                log_e("malloc uart%d rx buffer(%ld) failed", uart_num, uart_datas->config.uart[uart_num].buffer);
                return false;
            }
        }

        snprintf((char *)uart_datas->buffer[uart_num], UART_BUFFER_SIZE, "uart%d_rx", uart_num);
        if (
            !uart_datas->task_handle[uart_num] &&
            xTaskCreatePinnedToCore(
                uart_rx_thread,
                (char *)uart_datas->buffer[uart_num],
                2048,
                (void *const)uart_num,
                10,
                &uart_datas->task_handle[uart_num],
                portNUM_PROCESSORS - 1) != pdTRUE)
        // if (!uart_datas->task_handle[uart_num] && xTaskCreate(uart_rx_thread, (char *)uart_datas->buffer[uart_num], 2048, uart_num, 15, &uart_datas->task_handle[uart_num]) != pdTRUE)
        {
            log_e("create uart%d rx thread failed", uart_num);
            uart_free_rb(uart_num);
            return false;
        }
    }
    return true;
}

static bool uart_config_init(void)
{
    uart_datas = malloc(sizeof(uart_data_s));
    log_i("malloc uart_config(%d) : %p", sizeof(uart_data_s), uart_datas);
    if (!uart_datas)
    {
        log_e("malloc uart_datas failed");
        return false;
    }
    memset(uart_datas, 0, sizeof(uart_data_s));
    if (!config_get(CONFIG_ITEM_NAME, (uint8_t *)&uart_datas->config, sizeof(uart_data_s)))
    {
        log_w("Not find " CONFIG_ITEM_NAME ", Use default config");
        /* 默认配置 */
        for (int i = 0; i < UART_NUM_MAX; i++)
        {
            uart_datas->config.uart[i].buffer = 4096;
            uart_datas->config.uart[i].baud_rate = 115200;
            uart_datas->config.uart[i].data_bits = UART_DATA_8_BITS;
            uart_datas->config.uart[i].parity = UART_PARITY_DISABLE;
            uart_datas->config.uart[i].stop_bits = UART_STOP_BITS_1;
            uart_datas->config.uart[i].io_map.tx = -1;
            uart_datas->config.uart[i].io_map.rx = -1;
            uart_datas->config.uart[i].io_map.rts = -1;
            uart_datas->config.uart[i].io_map.cts = -1;
        }
    }
    for (int i = 0; i < UART_NUM_MAX; i++)
    {
        if (uart_datas->config.uart[i].enable)
            uart_start(i, true);
    }
    return true;
}
static bool uart_config_save(void)
{
    if (config_set(CONFIG_ITEM_NAME, sizeof(uart_configs_s), (uint8_t *)&uart_datas->config))
        return config_commit();
    return false;
}
static uint16_t uart(http_server_t server, httpd_ws_frame_t *frame, void *data)
{
    if (data) /* set */
    {
        /*
        {
            "uart":[
                {
                    "enable":true,
                    "buffer":30000,
                    "io_map":{
                        "tx":1,
                        "rx":2,
                        "rts":3,
                        "cts":4
                    }
                }
            ],
            ...
        }
         */
        if (cJSON_HasObjectItem(data, "uart"))
        {
            log_i("process uart config");
            cJSON *uart = cJSON_GetObjectItem(data, "uart");
            if (cJSON_IsArray(uart))
            {
                uint8_t change = 0;
                uint8_t enable = 0;
                uint32_t buffer[UART_NUM_MAX] = {0};
                uint8_t tx[UART_NUM_MAX] = {0};
                uint8_t rx[UART_NUM_MAX] = {0};
                uint8_t rts[UART_NUM_MAX] = {0};
                uint8_t cts[UART_NUM_MAX] = {0};
                for (int i = 0; i < UART_NUM_MAX; i++)
                {
                    cJSON *item = cJSON_GetArrayItem(uart, i);
                    if (cJSON_IsObject(item))
                    {
                        cJSON *enable_item = cJSON_GetObjectItem(item, "enable");
                        cJSON *buffer_item = cJSON_GetObjectItem(item, "buffer");
                        cJSON *io_map = cJSON_GetObjectItem(item, "io_map");
                        if (!enable_item || !buffer_item || !io_map)
                            continue;

                        enable |= (uart_datas->config.uart[i].enable << i);
                        buffer[i] = uart_datas->config.uart[i].buffer;
                        tx[i] = uart_datas->config.uart[i].io_map.tx;
                        rx[i] = uart_datas->config.uart[i].io_map.rx;
                        rts[i] = uart_datas->config.uart[i].io_map.rts;
                        cts[i] = uart_datas->config.uart[i].io_map.cts;
                        if (cJSON_IsBool(enable_item))
                        {
                            if (uart_datas->config.uart[i].enable != cJSON_IsTrue(enable_item))
                            {
                                change |= (1 << i);
                                if (cJSON_IsTrue(enable_item))
                                    enable |= (cJSON_IsTrue(enable_item) << i);
                                else
                                    enable &= ~(1 << i);
                            }
                        }
                        if (cJSON_IsNumber(buffer_item))
                        {
                            if (uart_datas->config.uart[i].buffer != (uint32_t)buffer_item->valueint)
                            {
                                change |= (1 << i);
                                buffer[i] = (uint32_t)buffer_item->valueint;
                            }
                        }
                        if (cJSON_IsObject(io_map))
                        {
                            cJSON *tx_item = cJSON_GetObjectItem(io_map, "TX");
                            cJSON *rx_item = cJSON_GetObjectItem(io_map, "RX");
                            cJSON *rts_item = cJSON_GetObjectItem(io_map, "RST");
                            cJSON *cts_item = cJSON_GetObjectItem(io_map, "CTS");
                            if (!tx_item || !rx_item || !rts_item || !cts_item)
                                continue;
                            if (cJSON_IsNumber(tx_item))
                            {
                                if (GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.tx) != (uint8_t)tx_item->valueint)
                                {
                                    change |= (1 << i);
                                    tx[i] = (uint8_t)tx_item->valueint;
                                }
                            }

                            if (cJSON_IsNumber(rx_item))
                            {
                                if (GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.rx) != (uint8_t)rx_item->valueint)
                                {
                                    change |= (1 << i);
                                    rx[i] = (uint8_t)rx_item->valueint;
                                }
                            }

                            if (cJSON_IsNumber(rts_item))
                            {
                                if (GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.rts) != (uint8_t)rts_item->valueint)
                                {
                                    change |= (1 << i);
                                    rts[i] = (uint8_t)rts_item->valueint;
                                }
                            }

                            if (cJSON_IsNumber(cts_item))
                            {
                                if (GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.cts) != (uint8_t)cts_item->valueint)
                                {
                                    change |= (1 << i);
                                    cts[i] = (uint8_t)cts_item->valueint;
                                }
                            }
                        }
                    }
                }
                if (change)
                {
                    char *str = (char *)server->data;
                    uint16_t source_len = strlen(str);
                    uint16_t len = source_len;
                    len += sprintf(&str[len], "\"uart\":[");
                    for (uint8_t i = 0; i < UART_NUM_MAX; i++)
                    {
                        if (!((change >> i) & 1))
                        {
                            len += sprintf(&str[len], "{\"code\":%d},", 0);
                            continue;
                        }
                        log_w("uart%d change : enable:%d buffer:%ld, tx:%d, rx:%d, rts:%d, cts:%d",
                              i, (enable >> i) & 1, buffer[i], tx[i], rx[i], rts[i], cts[i]);
                        uart_datas->config.uart[i].enable = (enable >> i) & 1;
                        if (uart_datas->config.uart[i].enable && !uart_config_check_io(tx[i], rx[i], rts[i], cts[i]))
                        {
                            len += sprintf(&str[len], "{\"code\":%d, \"msg\":\"IO冲突\"},", -1);
                            continue;
                        }
                        uart_datas->config.uart[i].buffer = buffer[i];
                        uart_datas->config.uart[i].io_map.tx = tx[i];
                        uart_datas->config.uart[i].io_map.rx = rx[i];
                        uart_datas->config.uart[i].io_map.rts = rts[i];
                        uart_datas->config.uart[i].io_map.cts = cts[i];
                        if (uart_start(i, uart_datas->config.uart[i].enable))
                            len += sprintf(&str[len], "{\"code\":%d},", 1);
                        else
                            len += sprintf(&str[len], "{\"code\":%d, \"msg\":\"配置失败\"},", -1);
                    }
                    if (!uart_config_save())
                        len += sprintf(&str[len], "{\"code\":%d, \"msg\":\"保存失败\"},", -1);
                    len -= 1;
                    len += sprintf(&str[len], "],");
                    return len - source_len;
                }
            }
        }
        return 0;
    }
    else /* get */
    {
        char *str = (char *)server->data;
        uint16_t source_len = strlen(str);
        uint16_t len = source_len;
        len += sprintf(&str[len], "\"uart\":[");
        for (int i = 0; i < UART_NUM_MAX; i++)
        {
            len += sprintf(&str[len], "{");
            len += sprintf(&str[len], "\"enable\":%s,", uart_datas->config.uart[i].enable ? "true" : "false");
            len += sprintf(&str[len], "\"buffer\":%ld,", uart_datas->config.uart[i].buffer);
            len += sprintf(&str[len], "\"io_map\":{");
            len += sprintf(&str[len], "\"TX\":%d,", GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.tx));
            len += sprintf(&str[len], "\"RX\":%d,", GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.rx));
            len += sprintf(&str[len], "\"RST\":%d,", GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.rts));
            len += sprintf(&str[len], "\"CTS\":%d", GET_CONFIG_GPIO(uart_datas->config.uart[i].io_map.cts));
            len += sprintf(&str[len], "}},");
        }
        len -= 1;
        len += sprintf(&str[len], "],");
        return len - source_len;
    }
}

static void uart_fun(http_server_t server, httpd_ws_frame_t *frame, void *data)
{
    if (!cJSON_HasObjectItem(data, "id"))
        goto uart_fun_failed;
    uint8_t uart_num = cJSON_GetObjectItem(data, "id")->valueint;
    if (uart_num >= UART_NUM_MAX)
        goto uart_fun_failed;
    /* 转发数据到串口 */
    if (cJSON_HasObjectItem(data, "msg"))
    {
        cJSON *msg = cJSON_GetObjectItem(data, "msg");
        if (cJSON_IsString(msg))
        {
            char *str = cJSON_GetStringValue(msg);
            if (str)
            {
                size_t data_len = 0;
                char *data = (char *)uart_datas->writeBuffer[uart_num];
                mbedtls_base64_decode(NULL, 0, &data_len, (const uint8_t *)str, strlen(str));
                if (!data_len)
                {
                    ws_reply_status(server, frame, "uart", -3);
                    return;
                }
                if (data_len > UART_ENCODED_DATA_MAX)
                {
                    ws_reply_status(server, frame, "uart", -4);
                    return;
                }
                if (!mbedtls_base64_decode((uint8_t *)data, UART_ENCODED_DATA_MAX, &data_len, (const uint8_t *)str, strlen(str)))
                {
                    gpio_set_level(GPIO_NUM_3, 0);
                    uart_write_bytes(uart_num, data, data_len);
                    gpio_set_level(GPIO_NUM_3, 1);
                    ws_reply_status(server, frame, "uart", 1);
                }
                else
                    ws_reply_status(server, frame, "uart", -5);
            }
        }
        else
            ws_reply_status(server, frame, "uart", -2);
        return;
    }
    else if (cJSON_HasObjectItem(data, "config"))
    {
        cJSON *item = cJSON_GetObjectItem(data, "config");
        if (cJSON_IsObject(item))
        {
            cJSON *baudrate = cJSON_GetObjectItem(item, "baudrate");
            cJSON *databits = cJSON_GetObjectItem(item, "databits");
            cJSON *parity_item = cJSON_GetObjectItem(item, "parity");
            cJSON *stopbits = cJSON_GetObjectItem(item, "stopbits");
            if (!baudrate || !databits || !parity_item || !stopbits)
            {
                ws_reply_status(server, frame, "uart", -7);
                return;
            }
            uint8_t change = 0;
            uart_storage_t config = &uart_datas->config.uart[uart_num];
            uint32_t baud_rate = config->baud_rate;
            uint8_t data_bits = config->data_bits;
            uint8_t parity = config->parity;
            uint8_t stop_bits = config->stop_bits;
            if (cJSON_IsNumber(baudrate))
            {
                if (baud_rate != (uint32_t)baudrate->valueint)
                {
                    change = 1;
                    baud_rate = (uint32_t)baudrate->valueint;
                }
            }
            else
            {
                ws_reply_status(server, frame, "uart", -8);
                return;
            }
            if (cJSON_IsNumber(databits))
            {
                if (data_bits != (uint8_t)databits->valueint)
                {
                    change = 1;
                    data_bits = (uint8_t)databits->valueint;
                }
            }
            else
            {
                ws_reply_status(server, frame, "uart", -9);
                return;
            }
            if (cJSON_IsNumber(parity_item))
            {
                uint8_t parity_temp = (uint8_t)parity_item->valueint;
                if (parity_temp)
                    parity_temp++;
                if (parity != parity_temp)
                {
                    change = 1;
                    parity = parity_temp;
                }
            }
            else
            {
                ws_reply_status(server, frame, "uart", -10);
                return;
            }
            if (cJSON_IsNumber(stopbits))
            {
                if (stop_bits != ((uint8_t)stopbits->valueint + 1))
                {
                    change = 1;
                    stop_bits = (uint8_t)stopbits->valueint;
                    stop_bits++;
                }
            }
            else
            {
                ws_reply_status(server, frame, "uart", -11);
                return;
            }
            if (change)
            {
                if (!uart_config_check(baud_rate, data_bits, parity, stop_bits))
                {
                    ws_reply_status(server, frame, "uart", -12);
                    return;
                }
                config->baud_rate = baud_rate;
                config->data_bits = data_bits;
                config->parity = parity;
                config->stop_bits = stop_bits;
                if (!uart_start(uart_num, config->enable) || !uart_config_save())
                {
                    ws_reply_status(server, frame, "uart", -13);
                    return;
                }
                else
                    ws_reply_status(server, frame, "uart", 1);
            }
            else
                ws_reply_status(server, frame, "uart", 0);
        }
        else
            ws_reply_status(server, frame, "uart", -6);
    }
    else if (cJSON_HasObjectItem(data, "listen"))
    {
        cJSON *listen = cJSON_GetObjectItem(data, "listen");
        // uart_storage_t config = &uart_datas->config.uart[uart_num];
        if (cJSON_IsBool(listen))
        {
            if (cJSON_IsTrue(listen))
                uart_datas->listen_rx |= (1 << uart_num);
            else
                uart_datas->listen_rx &= ~(1 << uart_num);
            ws_reply_status(server, frame, "uart", 2);
        }
        else
            ws_reply_status(server, frame, "uart", -14);
        return;
    }
    else if (cJSON_HasObjectItem(data, "rts"))
    {
        cJSON *rts = cJSON_GetObjectItem(data, "rts");
        uart_storage_t config = &uart_datas->config.uart[uart_num];
        if (cJSON_IsBool(rts) && config->io_map.rts != 255)
        {
            uart_set_rts(uart_num, cJSON_IsTrue(rts));
            ws_reply_status(server, frame, "uart", 3);
            return;
        }
        else
            ws_reply_status(server, frame, "uart", -15);
    }
    else if (cJSON_HasObjectItem(data, "cts"))
    {
        cJSON *cts = cJSON_GetObjectItem(data, "cts");
        uart_storage_t config = &uart_datas->config.uart[uart_num];
        if (cJSON_IsBool(cts) && config->io_map.cts != 255)
        {
            uart_set_rts(uart_num, cJSON_IsTrue(cts));
            ws_reply_status(server, frame, "uart", 4);
            return;
        }
        else
            ws_reply_status(server, frame, "uart", -16);
    }
    else
        goto uart_fun_failed;
    return;
uart_fun_failed:
    ws_reply_status(server, frame, "uart", -1);
}
/* uart_set_rts */
/* uart_set_dtr */

static void api_uart_init(void)
{
    if (!uart_config_init())
        return;
#if API_ENABLE_CONFIG_IO
    io_config_add(uart);
#endif
    ADD_API_ITEM_ALIAS("uart", uart_fun);
}
ADD_API(api_uart_init)
#endif
